package cn.aitrox.ry.util;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 数据集合操作
 */
public class ArrayUtil {
    // 将map.entrySet()转换成list
    public static <T> List<Map.Entry<String, T>> sortMapByStringKey(Map<String, T> map) {
        List<Map.Entry<String, T>> list = new ArrayList<Map.Entry<String, T>>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, T>>() {
            // 升序排序
            public int compare(Map.Entry<String, T> o1, Map.Entry<String, T> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        return list;
    }

    public static Map<String, String> queryUrl2Map(String qs) {
        if (qs.contains("?")) {
            qs = qs.substring(qs.indexOf("?") + 1, qs.length());
        }
        return queryString2Map(qs);
    }

    public static Map<String, String> queryString2Map(String qs) {
        return Splitter.on("&").withKeyValueSeparator("=").split(qs);
    }

    public static String map2QueryString(Map<String, Object> map) {
        return Joiner.on("&").withKeyValueSeparator("=").join(map);
    }

    public static Integer getMapInt(Map<String, Object> map, String key) throws NumberFormatException {
        String value = getMapString(map, key);
        if (!Strings.isNullOrEmpty(value)) {
            return Integer.parseInt(value);
        }
        return null;
    }

    public static Long getMapLong(Map<String, Object> map, String key) throws NumberFormatException {
        String value = getMapString(map, key);
        if (!Strings.isNullOrEmpty(value)) {
            return Long.parseLong(value);
        }
        return null;
    }

    public static Float getMapFloat(Map<String, Object> map, String key) {
        String value = getMapString(map, key);
        if (!Strings.isNullOrEmpty(value)) {
            return Float.parseFloat(value);
        }
        return null;
    }

    public static Double getMapDouble(Map<String, Object> map, String key) {
        String value = getMapString(map, key);
        if (!Strings.isNullOrEmpty(value)) {
            return Double.parseDouble(value);
        }
        return null;
    }

    public static BigDecimal getMapBigDecimal(Map<String, Object> map, String key) {
        String value = getMapString(map, key);
        if (!Strings.isNullOrEmpty(value)) {
            return new BigDecimal(value);
        }
        return null;
    }

    public static Date getMapDate(Map<String, Object> map, String key, SimpleDateFormat format) {
        String value = getMapString(map, key);
        if (!Strings.isNullOrEmpty(value)) {
            try {
                return format.parse(value);
            } catch (ParseException e) {
            }
        }
        return null;
    }

    public static Date getMapDate(Map<String, Object> map, String key, String format) throws ParseException {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return getMapDate(map, key, sf);
    }

    public static Date getMapDateTime(Map<String, Object> map, String key) {
        SimpleDateFormat df = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        return getMapDate(map, key, df);
    }

    public static Date getMapDateByLong(Map<String, Object> map, String key) {
        Long value = getMapLong(map, key);
        if (value != null) {
            return new Date(value);
        }
        return null;
    }

    /*
     * 字符串不做任何转换
     */
    public static String getMapText(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null)
            return value.toString();
        else
            return null;
    }

    /*
     * 字符串不做任何转换
     */
    public static String getMapString(Map<String, Object> map, String key, String defaultValue) {
        Object value = map.get(key);
        if (value != null)
            return value.toString();
        else
            return defaultValue;
    }

    /*
     * 字符串不做任何转换
     */
    public static String getMapStringVal(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null)
            return value.toString();
        else
            return null;
    }

    /*
     * 数组自动转换成json数组格式 字符串自动去掉头尾空格和回车
     */
    public static String getMapString(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            if (value instanceof ArrayList)
                return JSONUtil.toJson(value);
            else
                return StringUtil.purify(value.toString());
        }
        return null;
    }

    public static String[] getMapStringArr(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            return JSONUtil.fromJson(value.toString(), String[].class);
        }
        return new String[]{};
    }

    public static boolean getMapBoolean(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            return Boolean.parseBoolean(value.toString());
        }
        return false;
    }

    public static Boolean getMapBooleanSolo(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            return Boolean.parseBoolean(value.toString());
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> getMapMap(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            return (Map<String, Object>) value;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static List<Object> getMapList(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            return (List<Object>) value;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> getMapObjectList(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value != null) {
            return (List<T>) value;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static List<Long> getMapListLongType(Map<String, Object> map, String key) {
        Object value = map.get(key);
        List<Long> list = Lists.newArrayList();
        if (value != null) {
            List<Object> listo = (List<Object>) value;
            listo.forEach(o -> {
                if (o != null) {
                    if (o instanceof Long) {
                        list.add((Long) o);
                    } else if (o instanceof Integer) {
                        Integer integer = (Integer) o;
                        int i = integer;
                        list.add((long) i);
                    } else if (o instanceof String)
                        list.add(Long.parseLong(o.toString()));
                }
            });
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public static List<Integer> getMapListIntegerType(Map<String, Object> map, String key) {
        Object value = map.get(key);
        List<Integer> list = Lists.newArrayList();
        if (value != null) {
            List<Object> listo = (List<Object>) value;
            listo.forEach(o -> {
                if (o != null) {
                    if (o instanceof Integer) {
                        list.add((Integer) o);
                    } else if (o instanceof String) {
                        list.add(NumParseUtil.StringToInteger((String) o));
                    }
                }
            });
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public static List<String> getMapListStringType(Map<String, Object> map, String key) {
        Object value = map.get(key);
        List<String> list = Lists.newArrayList();
        if (value != null) {
            List<String> listo = (List<String>) value;
            listo.forEach(o -> {
                if (o != null) {
                    list.add(String.valueOf(o));
                }
            });
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> getMapList(Map<String, Object> map, String key, Class<T> c) throws Exception {
        Object value = map.get(key);
        List<Map<String, Object>> list = Lists.newArrayList();
        if (value != null) {
            List<Map<String, Object>> listo = (List<Map<String, Object>>) value;
            listo.forEach(o -> {
                if (o != null) {
                    list.add(o);
                }
            });
        }
        List<T> tList = Lists.newArrayList();
        for (Map<String, Object> mapInfo : list) {
            T t = Map2Object(mapInfo, c);
            tList.add(t);
        }
        return tList;
    }

    @SuppressWarnings("unchecked")
    public static List<Map<String, Object>> getMapListFromMapItem(Map<String, Object> map, String key, String childKey) {
        if (!map.containsKey(key)) {
            List<Map<String, Object>> list = Lists.newArrayList();
            return list;
        }

        Map<String, Object> childMap = (Map<String, Object>) map.get(key);
        return getMapListFromMapItem(childMap, childKey);
    }

    @SuppressWarnings("unchecked")
    public static List<Map<String, Object>> getMapListFromMapItem(Map<String, Object> map, String key) {
        List<Map<String, Object>> list = Lists.newArrayList();
        if (!map.containsKey(key))
            return list;

        Object value = map.get(key);
        if (value != null) {
            List<Map<String, Object>> listo = (List<Map<String, Object>>) value;
            listo.forEach(o -> {
                if (o != null) {
                    list.add(o);
                }
            });
        }
        return list;
    }

    public static <T> Object fieldValue(T t, String fieldName) throws Exception {
        Object value = null;
        Field fields[] = t.getClass().getDeclaredFields();
        Field.setAccessible(fields, true);
        for (Field field : fields) {
            if (field.equals(fieldName)) {
                value = field.get(t);
            }
        }
        return value;

    }

    public static Map<String, Object> filed2Map(Object obj) {
        Map<String, Object> map = Maps.newHashMap();
        Field[] fs = obj.getClass().getDeclaredFields();
        for (Field f : fs) {
            f.setAccessible(true);
            try {
                Object val = f.get(obj);
                map.put(f.getName(), val);
            } catch (Exception e) {
            }
        }
        return map;
    }

    public static <T> T Map2Object(Map<String, Object> map, Class<T> c) throws Exception {
        T t = c.newInstance();
        Field fields[] = c.getDeclaredFields();
        Field.setAccessible(fields, true);
        for (Field field : fields) {
            if (map.containsKey(field.getName())) {
                field.set(t, map.get(field.getName()));
            }
        }
        return t;
    }

    public static List<Long> transfer2Long(List<String> list) {
        List<Long> regionIdList = Lists.newArrayList();
        for (String str : list)
            regionIdList.add(Long.parseLong(str));
        return regionIdList;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public static void addvalidList(List value1, List value2) {
        for (Object obj2 : value2) {
            if (!value1.contains(obj2))
                value1.add(obj2);
        }
    }

    public static List<Long> bigInterger2Long(List<BigInteger> list) {
        List<Long> lList = Lists.newArrayList();
        list.forEach((bigInteger) -> lList.add(bigInteger.longValue()));
        return lList;
    }

    public static List<Long> string2Long(List<String> list) {
        List<Long> lList = Lists.newArrayList();
        list.forEach((str) -> lList.add(Long.parseLong(str)));
        return lList;
    }

    public static <T> List<T> removeRepeat(List<T> list) {
        Set<T> set = Sets.newHashSet();
        set.addAll(list);
        list = Lists.newArrayListWithCapacity(set.size());
        list.addAll(set);
        return list;
    }

    public static Integer[] stringToIntegers(String input, String delimiter) {
        if (Strings.isNullOrEmpty(input))
            return null;

        List<String> strings = Splitter.on(",").omitEmptyStrings().splitToList(input);
        Integer[] result = new Integer[strings.size()];
        for (int i = 0; i < strings.size(); i++) {
            result[i] = Integer.valueOf(strings.get(i));
        }
        return result;
    }

    /*
     * 判断List是否为空。
     */
    public static boolean isEmpty(List<?> list) {
        if (list == null || list.size() == 0)
            return true;
        else
            return false;
    }

    /*
     * 获取List数量，null是0
     */
    public static int size(List<?> list) {
        if (list == null || list.size() == 0)
            return 0;
        else
            return list.size();
    }

    /*
     * 判断Set是否为空。
     */
    public static boolean isEmpty(Set<?> set) {
        if (set == null || set.size() == 0)
            return true;
        else
            return false;
    }

    /*
     * 判断Map是否为空。
     */
    public static boolean isEmpty(Map<?, ?> map) {
        if (map == null || map.size() == 0)
            return true;
        else
            return false;
    }

    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    public static <T> T getFirstElement(List<T> list) {
        if (list != null && list.size() > 0) {
            return list.get(0);
        } else
            return null;
    }

    public static <T> boolean isInArray(T t, T[] arr) {
        if (t == null || arr == null || 0 == arr.length) {
            return false;
        }
        for (T element : arr) {
            if (element.equals(t)) {
                return true;
            }
        }
        return false;
    }

    /*
     * 把不为null的值放入map
     */
    public static <K, V> void putMapNotNull(Map<K, V> map, K key, V value) {
        if (value != null) {
            map.put(key, value);
        }
    }

    /*
     * 交集
     */
    public static Set<String> getSetIntersection(Set<String> set1, Set<String> set2) {
        Set<String> result = Sets.newHashSet();
        result.addAll(set1);
        result.retainAll(set2);
        return result;
    }

    /*
     * 并集
     */
    public static Set<String> getSetUnion(Set<String> set1, Set<String> set2) {
        Set<String> result = Sets.newHashSet();
        result.addAll(set1);
        result.addAll(set2);
        return result;
    }

    /*
     * 差集：set1 - set2
     */
    public static Set<String> getSetDifference(Set<String> set1, Set<String> set2) {
        Set<String> result = Sets.newHashSet();
        result.addAll(set1);
        result.removeAll(set2);
        return result;
    }

    /*
     * string数组转double数组
     */
    public static Double[] stringArrayToDoubleArray(String[] data) {
        Double[] doubles = new Double[data.length];
        for (int i = 0; i < data.length; i++) {
            doubles[i] = Double.valueOf(data[i]);
        }
        return doubles;
    }

    /**
     * set匹配结果
     *
     * @param set1
     * @param set2
     * @return set1有 && set2没有的
     */
    public static Set<String> removeSetResult(Set<String> set1, Set<String> set2) {
        Set<String> result = new HashSet();
        result.addAll(set1);
        result.removeAll(set2);
        return result;
    }
}